#pragma once
#include <iostream>
#include <unistd.h>
#include <cstring>
#include <sys/epoll.h>
#include "log_pro.hpp"
#include "nocopy.hpp"

int defaultSize = 128;

class Epoller : public Nocopy // 继承禁止拷贝的类
{
public:
    Epoller()
    {
        _fd = epoll_create(defaultSize); // 创建epoll模型
        if (_fd == -1)
        {
            lg(ERROR, "epoll_create fail %d: %s", errno, strerror(errno));
        }
    }

    void ctl(int op, int fd, uint32_t event)
    {
        int ret = 0;
        // op: EPOLL_CTL_DEL/EPOLL_CTL_ADD/EPOLL_CTL_MOD
        if (op == EPOLL_CTL_DEL) // 单独处理一下删除，仅仅是为了说明ctl第三个参数可以直接设置为nullptr
        {
            ret = epoll_ctl(_fd, op, fd, nullptr);
            if (ret == -1)
            {
                lg(ERROR, "epoll_ctl del fail %d: %s", errno, strerror(errno));
            }
        }
        else
        {
            // 生成ctl需要的第三个参数
            struct epoll_event Event;
            Event.events = event;
            Event.data.fd = fd;
            ret = epoll_ctl(_fd, op, fd, &Event);
            if (ret == -1)
            {
                lg(ERROR, "epoll_ctl mod or add fail %d: %s", errno, strerror(errno));
            }
        }
    }

    int getFd()
    {
        return _fd;
    }

    int wait(epoll_event *ev, int maxevent, int timeout = -1)
    {
        // 因为函数有返回值了，所以不需要在函数内部判断返回-1出错的情况
        return epoll_wait(_fd, ev, maxevent, timeout);
    }

    ~Epoller()
    {
        if (_fd != -1)
            close(_fd);
    }

private:
    int _fd;
};